package com.Txunda.fxw.base;

import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.AppCompatActivity;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.inputmethod.InputMethodManager;
import android.widget.AdapterView;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.RelativeLayout.LayoutParams;
import android.widget.Toast;

import com.Txunda.fxw.R;
import com.Txunda.fxw.base.fragment.FragmentParam;
import com.Txunda.fxw.base.utils.tool.AppManager;
import com.Txunda.fxw.base.utils.util.ListUtils;
import com.Txunda.fxw.base.web.ApiListener;
import com.Txunda.fxw.config.WeApplication;
import com.Txunda.fxw.tipstoast.Mydialog;
import com.Txunda.fxw.tipstoast.TipsToast;
import com.lidroid.xutils.ViewUtils;
import com.umeng.analytics.MobclickAgent;

import java.io.InterruptedIOException;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.net.UnknownServiceException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import butterknife.ButterKnife;
import butterknife.Unbinder;

public abstract class BaseActivity extends AppCompatActivity implements ApiListener {

    private FrameLayout content;
    private View progress;
    private View error;
    private ProgressDialog progressDialog;

    protected WeApplication application;

    protected BaseFragment currentFragment;

    private List<BaseFragment> fragments;

    private boolean isShowContent; // 当出错时标识是否显示错误页面
    protected boolean hasAnimiation = true; // 启动页面时是否带启动动画
    private Unbinder unbinder;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // 竖屏锁定
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        setContentView(R.layout.aty_base);
        // 管理Activity
        AppManager.getInstance().addActivity(this);
        // 初始化控件
        initControls();
        // 设置子布局
        setBasicContentView(getLayoutResId());
        ViewUtils.inject(this);
        unbinder = ButterKnife.bind(this);
        // 向用户展示信息前的准备工作在这个方法里处理
        preliminary();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        unbinder.unbind();
        AppManager.getInstance().killActivity(this);
    }

    @Override
    protected void onResume() {
        super.onResume();
        // 统计页面
        MobclickAgent.onPageStart(this.getClass().getSimpleName());
        // 统计时长
        MobclickAgent.onResume(this);
    }

    @Override
    protected void onPause() {
        super.onPause();
        MobclickAgent.onPageEnd(this.getClass().getSimpleName());
        MobclickAgent.onPause(this);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        // 点击空白隐藏键盘
        InputMethodManager mInputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
        if (event.getAction() == MotionEvent.ACTION_DOWN) {
            if (getCurrentFocus() != null) {
                if (getCurrentFocus().getWindowToken() != null) {
                    mInputMethodManager.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(),
                            InputMethodManager.HIDE_NOT_ALWAYS);
                }
            }
        }
        return super.onTouchEvent(event);
    }

    /**
     * 初始化控件
     */
    private void initControls() {
        content = findViewById(R.id.content);

        progress = View.inflate(this, R.layout.loading_content, null);
        ImageView loading_gifview = progress.findViewById(R.id.loading_gifview);

        error = View.inflate(this, R.layout.layout_error, null);
        error.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                requestData();
                content.removeView(error);
            }
        });
        progressDialog = new ProgressDialog(this, R.style.loading_dialog);
        progressDialog.setIndeterminate(true);
        progressDialog.setCancelable(false);
        progressDialog.setCanceledOnTouchOutside(false);

    }

    /**
     * 设置content的子布局
     */
    private void setBasicContentView(int layoutResId) {
        LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        View main = inflater.inflate(layoutResId, null);
        LayoutParams layoutParams = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
        main.setLayoutParams(layoutParams);
        content.addView(main);
    }

    /**
     * 向用户展示信息前的准备工作在这个方法里处理
     */
    private void preliminary() {
        application = (WeApplication) getApplication();
        // 初始化数据
        initialized();
        // 请求数据
        requestData();
    }

    /**
     * 用于设置页面布局
     */
    protected abstract int getLayoutResId();

    /**
     * <font color=#ff0000>如页面中没有添加Fragment则不用重写此方法</font><br/>
     * 当页面中有Fragment时返回他的容器id，没有时返回0即可
     */
    protected int getFragmentContainerId() {
        return 0;
    }

    /**
     * 初始化数据
     */
    protected abstract void initialized();


    protected abstract void requestData();

    // /** 当错误界面显示时的点击回调，确定不会显示时可以不重写 */
    // protected void onErrorLayoutClick() {
    // }

    public void onClick(View v) {
    }

    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_MENU) {
            // do nothing
            return true;
        }
        return super.onKeyDown(keyCode, event);
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        // TODO Auto-generated method stub
        super.onSaveInstanceState(outState);
    }

    // ============================== 启动Activity ==============================

    /**
     * 启动一个Activity
     *
     * @param className 将要启动的Activity的类名
     * @param options   传到将要启动Activity的Bundle，不传时为null
     */
    protected void startActivity(Class<?> className, Bundle options) {
        Intent intent = new Intent(this, className);
        if (options != null) {
            intent.putExtras(options);
        }
        startActivity(intent);
    }

    /**
     * 启动一个有会返回值的Activity
     *
     * @param className   将要启动的Activity的类名
     * @param options     传到将要启动Activity的Bundle，不传时为null
     * @param requestCode 请求码
     */
    protected void startActivityForResult(Class<?> className, Bundle options, int requestCode) {
        Intent intent = new Intent(this, className);
        if (options != null) {
            intent.putExtras(options);
        }
        startActivityForResult(intent, requestCode);
    }

    @Override
    public void startActivity(Intent intent) {
        super.startActivity(intent);
        if (hasAnimiation) {
            overridePendingTransition(R.anim.slide_right_in, R.anim.slide_left_out);
        }
    }

    @Override
    public void finish() {
        super.finish();
        if (hasAnimiation) {
            overridePendingTransition(R.anim.slide_left_in, R.anim.slide_right_out);
        }
    }

    // ================================ 启动Fragment =============================

    public void pushFragmentToBackStatck(Class<?> cls, Object data) {
        FragmentParam param = new FragmentParam();
        param.cls = cls;
        param.data = data;
        param.addToBackStack = true;
        processFragement(param);
    }

    public void addFragment(Class<?> cls, Object data) {
        FragmentParam param = new FragmentParam();
        param.cls = cls;
        param.data = data;
        param.addToBackStack = false;
        processFragement(param);
    }

    public void replaceFragment(Class<?> cls, Object data) {
        FragmentParam param = new FragmentParam();
        param.cls = cls;
        param.data = data;
        param.type = FragmentParam.TYPE.REPLACE;
        param.addToBackStack = false;
        processFragement(param);
    }

    public void goToFragment(Class<?> cls, Object data) {
        if (cls == null) {
            return;
        }
        BaseFragment fragment = (BaseFragment) getSupportFragmentManager().findFragmentByTag(cls.toString());
        if (fragment != null) {
            currentFragment = fragment;
            fragment.onBack(data);
        }
        getSupportFragmentManager().popBackStackImmediate(cls.toString(), 0);
    }

    public void popTopFragment(Object data) {
        FragmentManager fm = getSupportFragmentManager();
        fm.popBackStackImmediate();
        currentFragment = null;
        int cnt = fm.getBackStackEntryCount();
        String name = fm.getBackStackEntryAt(cnt - 1).getName();
        currentFragment = (BaseFragment) fm.findFragmentByTag(name);
        currentFragment.onBack(data);
    }

    public void popToRoot(Object data) {
        FragmentManager fm = getSupportFragmentManager();
        while (fm.getBackStackEntryCount() > 1) {
            fm.popBackStackImmediate();
        }
        popTopFragment(data);
    }

    protected String getFragmentTag(FragmentParam param) {
        StringBuilder sb = new StringBuilder(param.cls.toString());
        return sb.toString();
    }

    private void processFragement(FragmentParam param) {
        int containerId = getFragmentContainerId();
        Class<?> cls = param.cls;
        if (cls == null) {
            return;
        }
        try {
            String fragmentTag = getFragmentTag(param);
            BaseFragment fragment = (BaseFragment) getSupportFragmentManager().findFragmentByTag(fragmentTag);
            if (fragment == null) {
                fragment = (BaseFragment) cls.newInstance();
            }
            fragment.onComeIn(param.data);
            if (currentFragment != null) {
                currentFragment.onLeave();
            }

            if (fragments == null) {
                fragments = new ArrayList<BaseFragment>();
            }
            ListUtils.addDistinctEntry(fragments, fragment);

            FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
            if (param.type == FragmentParam.TYPE.ADD) {
                if (fragment.isAdded()) {
                    for (BaseFragment lastFragment : fragments) {
                        ft.hide(lastFragment);
                    }
                    currentFragment.onPause();
                    ft.show(fragment);
                    fragment.onResume();
                } else {
                    ft.add(containerId, fragment, fragmentTag);
                }
            } else {
                ft.replace(containerId, fragment, fragmentTag);
            }

            currentFragment = fragment;
            if (param.addToBackStack) {
                ft.addToBackStack(fragmentTag);
            }
            ft.commitAllowingStateLoss();

        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }

    // ============================ 信息提示方式 ============================

    /**
     * 含有标题、内容和确定按钮的对话框 -- 一般用来显示信息
     *
     * @param title
     * @param message
     */
    protected void showDialog(String title, String message) {
        showDialog(title, message, "确定", null);
    }

    /**
     * 含有标题、内容和一个按钮的对话框
     *
     * @param title
     * @param message
     * @param positiveText
     * @param listener
     */
    protected void showDialog(String title, String message, String positiveText,
                              DialogInterface.OnClickListener listener) {
        new AlertDialog.Builder(this).setTitle(title).setMessage(message).setPositiveButton(positiveText, listener)
                .create().show();
    }

    /**
     * 含有标题、内容和两个按钮的对话框
     *
     * @param title
     * @param message
     * @param positiveText
     * @param negativeText
     * @param positiveListener
     * @param negativeListener
     */
    protected void showDialog(String title, String message, String positiveText, String negativeText,
                              DialogInterface.OnClickListener positiveListener, DialogInterface.OnClickListener negativeListener) {
        new AlertDialog.Builder(this).setTitle(title).setMessage(message)
                .setPositiveButton(positiveText, positiveListener).setNegativeButton(negativeText, negativeListener)
                .create().show();
    }

    /**
     * 含有标题内容和两个按钮的类似IOS对话框
     *
     * @param title
     * @param message
     * @param positiveText
     * @param negativeText
     * @param listener
     * @param rightListener
     */
    protected void showmyDialog(String title, String message, String positiveText, String negativeText,
                                Mydialog.LeftListener listener, Mydialog.RightListener rightListener) {
        new Mydialog(this, title, message, positiveText, negativeText, listener, rightListener).show();
    }

    /**
     * 带有item的Dialog
     *
     * @param title
     * @param itemsId
     * @param listener
     */
    protected void showItemsDialog(String title, int itemsId, DialogInterface.OnClickListener listener) {
        new AlertDialog.Builder(this).setTitle(title).setItems(itemsId, listener).show();
    }

    /**
     * 带有item的Dialog
     *
     * @param title
     * @param listener
     */
    protected void showItemsDialog(String title, CharSequence[] items, DialogInterface.OnClickListener listener) {
        new AlertDialog.Builder(this).setTitle(title).setItems(items, listener).show();
    }

    protected void showToast(String text) {
        Toast toast = Toast.makeText(this, text, Toast.LENGTH_SHORT);
        toast.setGravity(Gravity.CENTER, 0, 0);
        toast.setText(text);
        toast.show();
    }

    // ====================== 加载条 ==========================

    private boolean isShowing = false;

    protected void showProgressContent() {
        isShowContent = true;
        isShowing = true;
        content.addView(progress);
    }

    protected void removeProgressContent() {
        if (isShowing) {
            isShowing = false;
            isShowContent = false;
            content.removeView(progress);
        }
    }

    protected void showProgressDialog() {
        isShowContent = false;
        if (!progressDialog.isShowing()) {
            progressDialog.show();
            progressDialog.setContentView(R.layout.loading_dialog);
        }
    }

    protected void removeProgressDialog() {
        if (progressDialog.isShowing()) {
            progressDialog.dismiss();
        }
    }

    // =================== API回调方法 ========================

    @Override
    public void onStarted() {
    }

    @Override
    public void onCancelled() {
        removeProgressContent();
        removeProgressDialog();
    }

    @Override
    public void onComplete(String requestUrl, String jsonStr) {
        removeProgressContent();
        removeProgressDialog();
    }

    @Override
    public void onError(String requestUrl, Map<String, String> error) {
        // showToast(error.get("message"));
        showTips(R.drawable.error, error.get("message"));
        removeProgressContent();
        removeProgressDialog();
    }

    @Override
    public void onException(Exception exception) {
        if (isShowContent) {
            content.addView(error);
        } else {
            if (exception instanceof SocketException || exception instanceof InterruptedIOException
                    || exception instanceof UnknownHostException || exception instanceof UnknownServiceException) {
                showToast(getString(R.string.network_anomaly));
            } else {
                showToast(getString(R.string.server_unknow_error));
            }
        }
        exception.printStackTrace();
        removeProgressContent();
        removeProgressDialog();
    }

    @Override
    public void onLoading(long total, long current, boolean isUploading) {

    }

    /**
     * 自定义toast
     *
     * @param iconResId
     * 图片
     * @param msgResId
     * 提示文字
     */
    private TipsToast tipsToast;

    protected void showTips(int iconResId, String tips) {
        if (tipsToast != null) {
            if (Build.VERSION.SDK_INT < Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
                tipsToast.cancel();
            }
        } else {
            tipsToast = TipsToast.makeText(this, tips, TipsToast.LENGTH_SHORT);
        }
        tipsToast.show();
        tipsToast.setIcon(iconResId);
        tipsToast.setText(tips);
    }

}
